from django.shortcuts import render, get_object_or_404, redirect, render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_protect
from django.template import RequestContext
from app.models import UserProfile
from app.forms import UserProfileForm, UserForm, PatientForm, DoctorForm, StaffForm
import lib.duo_web as duo
from django.conf import settings

# Copyright 2013 Medicloud team

# Create your views here.
@csrf_protect
def index(request):
    '''
    index(request) - Renders the base index.html template
    '''
    return render(request, 'index.html', {'title' : 'Home'})

@require_http_methods(['GET','POST'])
def contact(request):
    '''
    contact(request) - Renders the contact.html template (TODO)
    '''
    return render(request, 'contact.html', {'title' : 'Contact'})

@require_http_methods(['GET','POST'])
def about(request):
    '''
    about(request) - Renders the about.html template (TODO)
    '''
    return render(request, 'about.html', {'title' : 'About'})

# Note: The following registration methods might be able to be merged into one using the requested URL to determine which model to register. Though, you will
# need to make sure that the permissions are still checked appropriately!!!
@require_http_methods(['GET', 'POST'])
def register_patient(request):
    '''
    register_patient(request) - Renders the register.html template (TODO)
    '''
    context = RequestContext(request)
    registration_succeeded = False
    if request.method == 'POST':
        # Going by the example shown here http://www.tangowithdjango.com/book/chapters/login.html#creating-the-register-view, we need to save the User Model, UserProfile Model, and Sub Model (Patient, Doc, or Staff)
        user_form = UserForm(request.POST)
        user_profile_form = UserProfileForm(request.POST)
        patient_form = PatientForm(request.POST)
        # Check and make sure the forms are valid
        if user_form.is_valid() and user_profile_form.is_valid() and patient_form.is_valid():
            # Save the user form first
            user = user_form.save()
            user.set_password(user.password)
            user.save()
            # We want the user profile object, but *don't* want to save it to the DB yet
            user_profile = user_profile_form.save(commit=False)
            # Assign the user model to the UserProfile
            user_profile.user = user
            # Save the final object to the db
            user_profile.save()
            # Save the patient model appropriately
            patient_profile = patient_form.save(commit=False)
            patient_profile.patient = user_profile
            patient_profile.save()
            registration_succeeded = True
        else:
            print user_form.errors, user_profile_form.errors, patient_form.errors
    return render_to_response('register.html', {'title' : 'Register',
        'user_form' : UserForm(),
        'user_profile_form' : UserProfileForm(),
        'patient_form' : PatientForm()}, context)

@require_http_methods(['GET', 'POST'])
def register_doctor(request):
    '''
    register_doctor(request) - Renders the register.html template (TODO)
    '''
    return render(request, 'register.html', {'title' : 'Register'})

@require_http_methods(['GET', 'POST'])
def register_staff(request):
    '''
    register_staff(request) - Renders the register.html template (TODO)
    '''
    return render(request, 'register.html', {'title' : 'Register'})


@require_http_methods(['GET', 'POST'])
def logout_view(request):
    logout(request)
    return render(request, 'index.html', {'title' : 'Home', 'message' : 'You have successfully logged out.'})

@login_required
@require_http_methods(['GET', 'POST'])
def send_sms(request, success=None, fail='/login'):
    '''
    send_sms(request, success=None, fail='/login') - Performs the first stage of the SMS 2-factor authentication flow
    '''
    if not fail: fail = '/login'
    if not success: success = None
    # Perform secondary auth
    signed_request = duo.sign_request(settings.DUO_INTEGRATION_KEY, settings.DUO_SECRET_KEY, settings.DUO_APP_KEY, request.user.email)
    return render(request, 'sms.html', {
        'title' : 'SMS Verficiation',
        'duo_host' : settings.DUO_API_HOST,
        'duo_request' : signed_request,
        'duo_callback' : '/login/sms/check',
        'request' : request.user.email
        })

@login_required
@require_http_methods(['POST'])
def check_sms(request):
    '''
    check_sms(request) - Verifies the result obtained from the 2-factor authentication flow
    '''
    sig_response = request.POST['sig_response']
    authenticated_username = duo.verify_response(settings.DUO_INTEGRATION_KEY, settings.DUO_SECRET_KEY, settings.DUO_APP_KEY, sig_response)
    if authenticated_username:
        request.session['username'] = authenticated_username
        request.session['2fa'] = True
        return redirect('/profile')
    else:
        return redirect('/login')

@login_required
@require_http_methods(['GET','POST'])
def profile(request):
    '''
    profile(request) - Renders the profile.html template based on the user's role
    '''
    # request my context 
    context = RequestContext(request)

    u = request.user
    up = UserProfile.objects.get(user=u)

    context_dict = { 'title' : "UserProfile" }

    context_dict['UserName'] = up
    context_dict['title'] = up
    context_dict['FirstName'] = request.user.first_name
    context_dict['UserAddress1'] = up.address1
    context_dict['UserAddress2'] = up.address2
    context_dict['UserCity'] = up.city
    context_dict['UserState'] = up.state
    context_dict['UserZip'] = up.postal_code
    context_dict['UserHomePhone'] = up.home_phone
    context_dict['UserMobilePhone'] = up.mobile_phone

    return render_to_response('profile.html', context_dict, context )

@login_required
def profile_edit(request):
    '''
    profile_edit(request) - Allows users to edit their contact information
    '''
    # To be implemented
    pass

@login_required
def profile_records(request):
    '''
    profile_records(request) - Allows users to view their medical records
    '''
    if '2fa' not in request.session or not request.session['2fa'] == True:
        return send_sms(request, success='/profile/records')
    else:
        return render(request, 'profile_records.html')
